import {checkFileApi, uploadFileApi, mergeFileApi, uploadChunkFileApi} from "@/api/chat";
import {closeToast, showFailToast} from "vant";
import {UserMessage} from "@/types/webSocketMessageTypes";
import {ResultEnum} from "@/enums/requestEnum";

const MAX_CHUNK_SIZE = 104857600 // 100MB

export function uploadFile(file: File, userMessage: UserMessage, callback: Function) {
    if (!file) {
        return;
    }
    const uploadType = file.size <= MAX_CHUNK_SIZE ? 'single' : 'chunk';
    const checkFileInfo = {
        key: `${file.size}_${file.name}`,
        fileType: uploadType
    }
    checkFileApi(checkFileInfo)
        .then(resp => {
            if (resp.respCode == 200) {
                if (!resp.data) {
                    if (uploadType === 'single') {
                        uploadEntireFile(file, userMessage, callback);
                        return;
                    }
                    uploadChunkFile(file, userMessage, callback)
                    return;
                }
                callback(userMessage.id, true);
                return;
            }
            callback(userMessage.id, false);
            showFailToast(resp.msg);
        })
        .catch(error => {
            console.error(error);
            callback(userMessage.id, false);
            showFailToast('文件上传失败！');
        })
}

const uploadEntireFile = (file: File, userMessage: UserMessage, callback: Function) => {
    const formData = new FormData();
    formData.append('file', file);
    uploadFileApi(formData)
        .then(resp1 => {
            if (resp1.respCode === ResultEnum.SUCCESS) {
                callback(userMessage.id, true);
            } else {
                callback(userMessage.id, false);
                showFailToast(resp1.msg);
            }
        })
        .catch(error => {
            callback(userMessage.id, false);
            showFailToast("文件上传失败！");
            console.error(error);
        })
}


const uploadChunkFile = (file: File, userMessage: UserMessage, callback: Function) => {
    let chunkSize = 104857600 // 100MB
    let chunkNum = 1
    let chunkStart = 0
    let chunkEnd = (chunkStart + chunkSize) > file.size ? file.size : (chunkStart + chunkSize)
    let totalChunks = Math.ceil(file.size / chunkSize)
    let threadNum = totalChunks > 8 ? 8 : totalChunks
    let finishNum = 0
    let noError = true
    const blobSlice = File.prototype.slice;       //兼容方式获取slice方法
    userMessage.progress = 10;
    console.debug(`${file.name} 分片个数${totalChunks}`)

    let uploadChunk = () => {
        console.debug(`${file.name} 第${chunkNum}个分片开始上传`)

        const chunk_file = blobSlice.call(file, chunkStart, chunkEnd);
        let formData = new FormData()
        formData.append('chunkFile', chunk_file)
        formData.append("fileName", `${file.size}_${file.name}`)
        formData.append("chunkNum", chunkNum + "")
        uploadChunkFileApi(formData)
            .then((resp) => {
                if (resp.respCode === ResultEnum.SUCCESS) {
                    finishNum = finishNum + 1
                    userMessage.progress = Math.round(finishNum / totalChunks * 0.7 * 100)
                    console.debug(`${file.name}上传进度：${userMessage.progress}`)
                    if (finishNum === totalChunks) {
                        console.debug(`合并文件 ${file.name}`)
                        mergeFile(userMessage.id, file, totalChunks, callback)
                    }
                }
                if (resp.respCode === ResultEnum.ERROR) {
                    noError = false;
                    callback(userMessage.id, false);
                    showFailToast(resp.msg);
                }
            })
            .catch(error => {
                callback(userMessage.id, false);
                showFailToast("文件上传失败！");
                console.error(error);
            })
    }

    while (chunkNum <= threadNum && noError) {
        uploadChunk()
        chunkStart = chunkStart + chunkSize
        chunkEnd = chunkStart + chunkSize
        chunkEnd = chunkEnd > file.size ? file.size : chunkEnd
        chunkNum = chunkNum + 1
    }

    let preFinishNum = finishNum
    if (totalChunks > 8) {
        // 分片个数大于8，监听之前的8个请求，完成多少个就新建多少个请求
        let interval = setInterval(() => {
            // 较上次完成请求个数
            const num = finishNum - preFinishNum
            // 更新上次监听时请求完成个数
            preFinishNum = finishNum
            if (chunkNum > totalChunks) {
                clearInterval(interval)
            } else if (chunkNum <= totalChunks && num > 0) {
                for (let i = 0; i < num; i++) {
                    uploadChunk()
                    chunkStart = chunkStart + chunkSize
                    chunkEnd = chunkStart + chunkSize
                    chunkEnd = chunkEnd > file.size ? file.size : chunkEnd
                    chunkNum = chunkNum + 1
                }
            }
        }, 1)
    }

}


function mergeFile(id: number, file: File, totalChunks: number, callback: Function) {
    const data = {
        'fileName': `${file.size}_${file.name}`,
        'totalChunks': totalChunks
    }
    mergeFileApi(data)
        .then((resp) => {
            if (resp.respCode === ResultEnum.SUCCESS) {
                callback(id, true);
                return;
            }
            showFailToast(resp.msg);
        })
}